package independence.reflection
{
	import independence.core.IndyObject;
	
	/**
	 * The Method class represents an object's specific declared method: any public
	 * method declared at the class level.
	 * 
	 * @author TK, TK Assembled for Independence Glory.
	 */
	public final class Method extends IndyObject implements IMember
	{
		/**
		 * @protected	The class which this method is associated with.
		 */
		protected var clazz:Class;
		/**
		 * @protected	The string name of this method.
		 */
		protected var methodName:String;
		/**
		 * @protected	The return type of this method.
		 */
		protected var returnType:Class;
		/**
		 * @protected	Whether this method is static or not.
		 */
		protected var statik:Boolean;
		/**
		 * Constructs a new Method object.
		 * @param	clazz		The class object to which this method belongs.
		 * @param	methodName	The string name of the method.
		 * @param	returnType	The return type of this method.
		 * @param	statik		Whether the method is static or not.
		 */
		public function Method(clazz:Class, methodName:String, returnType:Class, statik:Boolean = false)
		{
			this.clazz = clazz;
			this.methodName = methodName;
			this.returnType = returnType;
			this.statik = statik;
		}
		/**
		 * Returns whether this method is static or not.
		 * @return	True if the method is static, false otherwise.
		 */
		public function isStatic():Boolean 
		{
			return this.statik;
		}
		/**
		 * Returns the class which declares this method.
		 * @return	The class which declares this method.
		 */
		public function getDeclaringClass():Class
		{
			return clazz;
		}
		/**
		 * Returns the name of this method.
		 * @return	The name of this method.
		 */
		public function getName():String
		{
			return methodName;
		}
		/**
		 * Returns the class of the return type of this method
		 * @return	The return type of this method.
		 */
		public function getReturnType():Class
		{
			return this.returnType;
		}
		/**
		 * Invokes this method on the <code>target</code> object with <code>arguments</code> parameters.
		 * @param	target		The object to invoke this method upon.
		 * @param	arguments	The arguments to pass to the method on invocation.
		 */
		public function invoke(target:Object, ...arguments):Object
		{
			return Function((statik ? clazz[methodName] : target[methodName])).apply(
				(statik ? this : target), arguments);
		}
		/**
		 * Returns a String representation of this <code>Method</code> object.
		 * @return	A String representation of this <code>Method</code>.
		 */
		public function toString():String
		{
			return "[Method " + this.methodName + "]";
		}
	}
}